import { fieldTypeColor } from "@/views/screenConfig/dataComponents/common";
import { md5 } from "@/utils/aesUtils";
import { deepClone, mergeObject } from "@/utils";

export default class ChartBase {
  constructor() {}

  // ---------- 私有属性 (禁止修改) ----------
  _info = {};
  _defaultOption = {};
  _defaultSeries = {};

  _dataPoolConfig = [];
  _styleOptionConfig = [];

  _defaultDataPoolConfigItem = {
    label: "字段",
    key: "field",
    type: ["string"],
    limit: 1,
    width: "100%",
    description: "",
  };

  // ---------- 私有方法 (禁止外部直接调用) ----------
  /**
   * 配置项列表 转换
   * @param styleOptionConfig 配置项列表
   * @returns styleOption 配置项
   * @private 私有方法
   */
  _transformStyleOptionConfig(styleOptionConfig) {
    let styleOption = {};

    const handle = (soc) => {
      let keys = soc.bindKeys.split("."),
        current = styleOption;

      keys.forEach((key, index) => {
        if (index === keys.length - 1) {
          // 最后一个 直接赋值
          current[key] = soc.controlValue;
        } else {
          // 不是最后 构建对象
          if (current[key] === undefined) {
            current[key] = {};
          }

          if (current[key].toString() === "[object Object]") {
            current = current[key];
          }
        }
      });
    };

    styleOptionConfig.forEach((soc) => {
      if (soc.isGroup) {
        soc.children.forEach((c_soc) => {
          handle(c_soc);
        });
      } else {
        handle(soc);
      }
    });
    return styleOption;
  }

  /**
   * 配置项 转换
   * @param styleOption 配置项
   * @returns styleOptionConfig 配置项列表
   */
  _transformStyleOption(styleOption) {
    const transform = (object, parent = []) => {
      let result = [];
      Object.keys(object).forEach((key) => {
        if (object[key].toString() === "[object Object]") {
          let arr = transform(object[key], [...parent, key]);
          result = result.concat(arr);
        } else {
          result.push({
            bindKeys: [...parent, key].join("."),
            controlValue: object[key],
          });
        }
      });
      return result;
    };
    return transform(styleOption);
  }

  _mergeStyleOptionConfig(old_array, new_array) {
    return old_array.reduce((r, c) => {
      let new_item =
        new_array.find((item) => item.bindKeys === c.bindKeys) || {};

      r.push({
        ...c,
        ...new_item,
      });
      return r;
    }, []);
  }

  // ---------- 公共方法 ----------

  /**
   * 校验字段配置项是否正确
   * @private
   */
  _verifyDataFieldConfig(dataPoolField) {
    let status = true;
    this._dataPoolConfig.forEach((dpc) => {
      if (dataPoolField[dpc.key] instanceof Array) {
        if (dpc.limit === -1 && dataPoolField[dpc.key].length > 0) {
        } else if (
          dpc.limit > 0 &&
          dataPoolField[dpc.key].length <= dpc.limit
        ) {
        } else {
          status = false;
          // console.warn(`[ ${dpc.key} ] 不满足配置要求`)
        }
      } else {
        status = false;
        // console.warn(`[ ${dpc.key} ] 不满足配置要求`)
      }
    });

    return status;
  }

  _handleDataSet(dimensions, source) {
    return {
      dimensions,
      source,
    };
  }

  _splitDataSet(dimensions, source) {
    let xData = [],
      yDatas = [];
    if (dimensions.length >= 1) {
      let xField = dimensions[0];

      xData = source.reduce((r, c) => {
        r.push(c[xField]);
        return r;
      }, []);
    }

    if (dimensions.length > 1) {
      for (let i = 1, len = dimensions.length; i < len; i++) {
        let yField = dimensions[i];
        let yData = source.reduce((r, c) => {
          r.push(c[yField]);
          return r;
        }, []);

        yDatas.push({
          name: yField,
          data: yData,
        });
      }
    }

    return {
      xData,
      yData: yDatas,
    };
  }

  /**
   * 获取数值轴字段
   * @param {*} dataPoolField
   * @returns
   */
  _handleDimensionsFields(dataPoolField) {
    let dimensions = [];
    if (this._verifyDataFieldConfig(dataPoolField)) {
      dimensions = dimensions.concat(dataPoolField.xField);

      Object.keys(dataPoolField)
        .filter((key) => key !== "xField")
        .forEach((key) => {
          if (dataPoolField[key] instanceof Array) {
            dimensions = dimensions.concat(dataPoolField[key]);
          }
        });

      return dimensions.reduce((r, c) => {
        if (!r.includes(c.fieldName)) r.push(c);
        return r;
      }, []);
    } else {
      return dimensions;
    }
  }

  _handleDimensions(dataPoolField) {
    return this._handleDimensionsFields(dataPoolField).reduce((r, c) => {
      r.push(c.fieldName);
      return r;
    }, []);
  }

  /**
   * 更新字段配置信息里面的描述字段
   * @param {*} dataField 数据集 数据表头
   * @param {*} dataPoolField 字段配置信息
   */
  _updateDataPoolField(dataField, dataPoolField) {
    let dataFieldMap = new Map();
    dataField.forEach((field) => {
      dataFieldMap.set(field.fieldName, field.fieldDescribe);
    });
    Object.keys(dataPoolField).forEach((key) => {
      dataPoolField[key].forEach((field) => {
        field.fieldDescribe = dataFieldMap.get(field.fieldName);
      });
    });
  }

  /**
   * 处理各字段对应的数据
   * @param {*} dataPoolField 字段配置
   * @param {*} dataList 数据集数据
   * @returns
   */
  _handledataPoolFieldData(dataPoolField, dataList) {
    // 所有key
    return Object.keys(dataPoolField).reduce((dr, dc) => {
      // key 对应的数组
      dr[dc] = dataPoolField[dc].reduce((fr, fc) => {
        fr.push({
          ...fc,
          dataList: dataList.reduce((er, ec) => {
            er.push(ec[fc.fieldName]);
            return er;
          }, []),
        });
        return fr;
      }, []);
      return dr;
    }, {});
  }

  getOption({
    dataField = [],
    dataList = [],
    dataTotal = 0,
    dataPoolField,
    styleOptionConfig = [],
    themeColor = [],
    themeStyle = {},
  }) {
    // 更新描述字段
    this._updateDataPoolField(dataField, dataPoolField);
    //
    const { xField, yField } = this._handledataPoolFieldData(
      dataPoolField,
      dataList
    );

    const xData = xField.length ? xField[0].dataList : [];

    let { option, series, config } =
      this._transformStyleOptionConfig(styleOptionConfig);

    let defaultOption = deepClone(this._defaultOption);
    let defaultSeries = deepClone(this._defaultSeries);

    if (config) {
      if (config?.xAxisConfig?.font.length) {
        defaultOption.xAxis.axisLabel.formatter = (item) => {
          let temp = item.slice(0, config.xAxisConfig.font.length);
          return (
            item.slice(0, config.xAxisConfig.font.length) +
            (item.length > temp.length ? "..." : "")
          );
        };
      }
    }

    // 先合并主题
    // if (defaultOption && themeStyle) defaultOption = mergeObject(defaultOption, themeStyle)
    // if (defaultSeries && themeStyle) defaultSeries = mergeObject(defaultSeries, themeStyle)

    // 再合并自定义配置项
    if (defaultOption && option)
      defaultOption = mergeObject(defaultOption, option);
    if (defaultSeries && series)
      defaultSeries = mergeObject(defaultSeries, series);

    defaultOption.color = themeColor;

    defaultOption.xAxis.data = xData;

    if (
      this._info.component === "e-chart" &&
      defaultOption.series &&
      defaultOption.series instanceof Array &&
      yField.length > 0
    ) {
      yField.forEach((field) => {
        defaultOption.series.push({
          name: field.fieldDescribe,
          ...defaultSeries,
          data: field.dataList,
        });
      });
    }

    return defaultOption;
  }

  /**
   * 获取图表基础信息
   * @returns info 图表基础信息
   */
  getInfo() {
    return {
      ...this._info,
    };
  }

  /**
   * 获取生成数据的配置项
   * @returns {*}
   */
  getDataPoolConfig() {
    return this._dataPoolConfig.reduce((r, c) => {
      r.push({
        ...this._defaultDataPoolConfigItem,
        ...c,
        color: fieldTypeColor[c.type[0]],
      });
      return r;
    }, []);
  }

  /**
   * 获取样式配置项
   * @returns {*}
   */
  getStyleOptionConfig() {
    return this._styleOptionConfig.reduce((r, c) => {
      r.push({
        ...c,
        key: md5(c.bindKeys.toString()),
      });
      return r;
    }, []);
  }

  /**
   * 图表点击事件
   * @param event EChart原生事件
   * @return {{label: string, value: string}} 需要返回当前点击的 系列名称 和对应数值
   */
  getClickData(event) {
    console.warn("请复写EChart图表点击事件方法");
    return {
      label: "",
      value: "",
    };
  }
}
